/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package net.flowas.genericcrud.service;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.flowas.genericcrud.audit.config.AnditConfiguration;
import net.flowas.genericcrud.RepositoryService;
import net.flowas.genericcrud.ResourceRegister;
import net.flowas.genericcrud.model.FilePathListener;
import net.flowas.genericcrud.rest.CrudConstant;
import net.flowas.genericcrud.rest.CrudRest;
import net.flowas.genericcrud.rest.CrudRestImpl;
import net.flowas.genericcrud.rest.FileResource;
import net.flowas.genericcrud.service.chain.CrudExecuteHandler;
import net.flowas.genericcrud.service.chain.DtoWrapeJpaHandler;
import net.flowas.genericcrud.service.chain.I18nRegister;
import net.flowas.genericcrud.service.chain.ProcesserRegister;
import net.flowas.genericcrud.service.impl.ImageScale;
import net.flowas.genericcrud.service.impl.JpaRepositoryService;
import net.flowas.genericcrud.service.impl.RequestDispatcher;
import net.flowas.genericcrud.service.impl.TopRepositoryService;

/**
 * 服务配置类.
 * 
 * @author Administrator
 */
public class ServiceConfiguration {
  private static final Logger LOG = LoggerFactory.getLogger(ServiceConfiguration.class);
  private ConfigInfo configInfo;
  private Map addons;

  private CrudRest crudRest;

  private EntityManagerFactory entityManagerFactory;
  
  private DtoWrapeJpaHandler dtoWrapeJpaHandler;
  private ProcesserRegister processerRegister;
  private ViewConfig uiSettings;
  private I18nRegister i18nRegister;
  private RepositoryService customerRepositoryService;
  private List<RepositoryService> addtionalRepositoryServicies;
  /**
   * 对外接口服务
   */
  private TopRepositoryService topRepositoryService;
  /**
   * entityToDto-mapper.xml配置注册器
   * @return
   */
  public ResourceRegister getEntityToDtoSettingsRegister() {
	return dtoWrapeJpaHandler;
  }
  /**
   * customerProcesser.xml配置注册器
   * @return
   */
  public ResourceRegister getProcesserRegister() {
		return processerRegister;
  }
  /**
   * uiSetting.xml配置注册器
   * @return
   */
  public ResourceRegister getUiSettingsRegister() {
		return uiSettings;
  }
  
	public I18nRegister getI18nRegister() {
		return i18nRegister;
	}
	
    public RepositoryService getTopRepositoryService() {
		return topRepositoryService;
	}
    public void setAddtionalRepositoryServicies(List<RepositoryService> customerRepositoryServicies) {
		this.addtionalRepositoryServicies = customerRepositoryServicies;
	}
    public void setCustomerRepositoryService(RepositoryService customerRepositoryService) {
		this.customerRepositoryService = customerRepositoryService;
	}
/**
   * 系统的初始化配置.
   */
  public void init() {
    String fileStorage = configInfo.getFileStoragePath();
    File dir = new File(fileStorage);
    if (!dir.exists()) {
      dir.mkdirs();
      LOG.warn("created directory:" + dir.getAbsolutePath());
    }
    if (entityManagerFactory == null) {
      entityManagerFactory = Persistence
          .createEntityManagerFactory(configInfo.getPersistenceUnitName());
    }
    if(addons==null) {
    	addons = new HashMap();
    }
    EntityManager em = entityManagerFactory.createEntityManager();
    if(configInfo.getWebApplicationUrl()!=null) {
    	FilePathListener.setBasePath(configInfo.getWebApplicationUrl()+CrudConstant.DOWNLOAD_PREFIX);
    }
    topRepositoryService = new TopRepositoryService();
    RequestDispatcher dispatcher = new RequestDispatcher();
    topRepositoryService.setDispatcher(dispatcher);
    processerRegister =new ProcesserRegister();
    processerRegister.initDefaultListeners();
    dispatcher.setProcesserRegister(processerRegister);
    uiSettings = new ViewConfig();
    uiSettings.setFacade(dispatcher);
    i18nRegister=new I18nRegister();
	uiSettings.setI18nRegister(i18nRegister);
    uiSettings.initViewConfig();
    CrudRestImpl crudRestInternal = new CrudRestImpl();
    FileResource fileResource = crudRestInternal.getFileResource();
    fileResource.setFileStoragePath(configInfo.getFileStoragePath());    
    CrudExecuteHandler jpaHandler;
    if(customerRepositoryService!=null) {
    	jpaHandler = new CrudExecuteHandler(null,customerRepositoryService);
        dispatcher.registHandler(jpaHandler);
    	fileResource.setViewHandler(customerRepositoryService);     	
    } else {
    	AnditConfiguration auditConfig = new AnditConfiguration();
        auditConfig.setEm(em);
        auditConfig.init();
        addons.put("audit", auditConfig.getAuditResource());
        JpaRepositoryService jpaHandlerIml = new JpaRepositoryService();
        jpaHandlerIml.setEntityManager(em);
        jpaHandlerIml.setViewConfig(uiSettings);
        TransactionProxy proxy = TransactionProxy.getInstance();
        proxy.setEntityManager(em);
        RepositoryService jpaService = proxy.createProxy(jpaHandlerIml);    
        jpaHandler = new CrudExecuteHandler(auditConfig.getAuditHandler(),jpaService);
        dispatcher.registHandler(jpaHandler);       
        fileResource.setViewHandler(jpaService);
        if(addtionalRepositoryServicies!=null) {
        	for(RepositoryService service: addtionalRepositoryServicies) {
            	CrudExecuteHandler crud = new CrudExecuteHandler(null/*auditConfig.getAuditHandler()*/, service); 
            	dispatcher.registHandler(crud);
            }        	
        }
    }
    dtoWrapeJpaHandler = new DtoWrapeJpaHandler(jpaHandler,dispatcher);    
    ImageScale thumbnailGenerator = new ImageScale();
    thumbnailGenerator.setFileStoragePath(configInfo.getFileStoragePath());
    thumbnailGenerator.setThumbnailHeight(configInfo.getThumbnailHeight());
    thumbnailGenerator.setThumbnailWidth(configInfo.getThumbnailWidth());
    fileResource.setThumbnailGenerator(thumbnailGenerator);
    crudRestInternal.getItemsResource().setDispatcher(dispatcher);
    crudRestInternal.getItemsResource().setService(topRepositoryService);
    crudRestInternal.getI18nResource().setViewConfig(uiSettings);
    crudRestInternal.setAddons(addons);
    crudRest = crudRestInternal;
  }

  /**
   * 获取增删改查的Rest顶级资源.
   * @return
   */
  public CrudRest getCrudRest() {
    if (crudRest == null) {
      throw new IllegalStateException("Please invoke init() first");
    }
    return crudRest;
  }

  public void setConfigInfo(ConfigInfo configInfo) {
    this.configInfo = configInfo;
  }

  public void setAddons(Map addons) {
    this.addons = addons;
  }

  public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
    this.entityManagerFactory = entityManagerFactory;
  }

}
